#!/usr/bin/env python
# -*- coding: utf-8 -*
'''
Socjum Class
Created on 2010-07-01

@author: apito
'''
import urllib2
import os
import sys
import threading
import cookielib
import socket
import poster
import Image
import tempfile
from BeautifulSoup import  BeautifulSoup
#reload sys and set encoding to utf-8 because indows sucks
__version__=0.2
reload(sys)
sys.setdefaultencoding('utf-8')
class Socjum(object):
	'''Class for handle socjum.pl website to upload fotos'''
	def __init__(self):
		self.ONLINE = False #start Offline
		self.Hosts = [] #Lista z nazwami hostów społeczności
		self.CURRENT = '' #społeczność do której aktualnie jest się zalogowanym
		#zostanie użyta jako domyślna
	# Add Cookie Handle 
		self.cookie = self._MyCookieJar()
	# Create opener and requeue object to fetch data streaming
		self.opener=poster.streaminghttp.register_openers()	
		self.opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie))
		
	def login(self, login, password): 
		'''Return None on success or Message on failure
		'''
		if(login == ''):
			return u"Nie podano loginu"
		if(password == ''):
			return u"Nie podano hasła"
		url_login ="http://socjum.socjum.pl/zaloguj"#Tworzenie linku do logowania
		params = {'login': login, 'password': password}
		datagen, headers = poster.encode.multipart_encode(params)
		request = urllib2.Request(url_login, datagen, headers)
		try:
			result = urllib2.urlopen(request)
		except urllib2.HTTPError, errno:
			return str(errno)

		html = result.read()
		p=BeautifulSoup(html)
		stripe=p.find(id='stripe')
		if stripe:
			if stripe.find(id='stripe_register'):#pasek rejestracji, nie występuje jak jesteśmy zalogowani
				return u'Niepoprane done. Zaloguj ponownie.'
			else:
				hosts = stripe.findAll('option') #wyszukujemy hosty społczności do których należymy
				self.Hosts=[]#czyścimy tablicę hostów
				for i in hosts:
					i = i.string#pobranie tekstu z opcji
					if i != "Szukaj...": # Not found Szukaj...
						self.Hosts.append(i)#dodajemy host do listy
				#login correct
				self.ONLINE = True #ustawiamy status na ONLINE
				self.CURRENT=self.Hosts[0]#ustawienie bieżącego hosta na pierwszy znaleziony
				return 
		else:
			return u'Błąd ładowania strony.'
		result.close()
	def logout(self, retry=0):
		'''Wylogowuje z sesji socjum
		Jeżeli wylogowanie nie powiedzie się jeden raz próbuje drugi
		Zwraca 1 przy wylogowaniu i 0 w innym razie'''
		try:
			log = urllib2.Request("http://socjum.socjum.pl/wyloguj")
		except urllib2.URLError:
			if retry ==0:
				self.logout(retry=1)
			else:
				return 0
		self.ONLINE = False
		return 1
	
		'''Working on UPLOAD'''
	def upload(self,host,albumID, photos, limit=20):
		if self.ONLINE == False:
			self.logout()
			return None, u"Nie jesteś zalogowany"
		if host == '':
			return None, u"Nie podano hosta do uploadu zdjęć"
		if albumID =="":
			return  None, u"Nie podano numeru albumu"
		if len(photos) < 1:
			return None, u"Brak plików"	
			
		return self._Upload(host,albumID, photos,limit,self.cookie), None
					
#Upload Class 
	class _Upload(threading.Thread):
		'''Upload photos to website'''
		def __init__(self, host, albumID, photos, limit, cookie):
			'''host is socjum host, albumID is galery id on this host,
			 photos are list of file path limit is max photos per pack'''		
			threading.Thread.__init__(self)
			############3
			self._running = False
			self.limit = limit
			self.cookie = cookie
			self.host = host
			self.albumID = albumID
			self.photos = []
			list = []
			i=1
			print 'zdjęć ', len(photos)
			for photo in photos:
				list.append(photo)
				if len(list) == self.limit or len(photos)== i:
					self.photos.append(list) 
					list=[]
				i+=1		
			self.packs = len(self.photos)
			print "liczba cześci ", self.packs
			self.part = 0#numer przetwarzanej częśći
			self.size = 0 #ilość bajtów do wysłania w 'body' 
			self.sent = 0 #ilość wysłanych danych
			self.status = 0 # 1 -OK, 2-Error, 3-tworzenie miniatur, 4 -wysyłanie
			self.info = '' #dodaję takie coś żeby można to jakoś wykorzystać zamiast pronta do wyłapywania błędów		
			############
		
		def run(self):
			if len(self.photos) ==0:
				print u"Brak paczek do wysyłki"
			else:
				head = ['POST /galeria/dodaj_istniejaca_save HTTP/1.1']
				head.append('Host: %s'% self.host)
				head.append('User-Agent: Python-urllib/%s'% urllib2.__version__)##User-Agent must be the same as with loging otherwise acces_denied is raise
				head.append('Accept: text/html;q=0.9,text/plain; q=0.1')
				head.append('Accept-Language: pl,en-us;q=0.7,en;q=0.3')
				rawHeader = "\r\n".join(head) ##Tworzenie głównego nagłówka
				
				self._running = True
				for part in self.photos:
				#tworzenie miniatur
					self.size = 0
					self.sent = 0
					self.status= 3
					self.part +=1
					self.thumbnails = []
					self.thumbnails.append(("idgaleria", self.albumID))#lsta na adresy miniatur
					i=1
				#otwieranie plików
					for plik in part:
						try:
							img = Image.open(plik)
						except IOError,e :
							print e
						if img.size > (1024, 1024): # Sprawdzamy czy obrazek ma rozmiar większy od 1024px
							tmpImg = tempfile.NamedTemporaryFile(suffix='.jpg')	
							img.thumbnail((1024,1024), Image.ANTIALIAS)
							img.save(tmpImg, "JPEG")	
							tmpImg.seek(0)
						else: #otwieramy orginalny obraz
							tmpImg = open(plik, 'rb')
						self.thumbnails.append(("foto"+str(i), tmpImg))
						i+=1#Licznik do nazw plików
					datagen, headers = poster.encode.multipart_encode(self.thumbnails)
					self.size = headers['Content-Length']				
				##Open socket
					s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
					s.connect((self.host, 80))
					self.status=4#wysyłanie
					Header = rawHeader +"\r\n"+ self.cookie.get_cookie()+"\r\n" #dodanie ciastka z sesją logowania
					for h in headers:
						Header+= "%s: %s\r\n" %(h, headers[h]) #dodanie wygenerowanych nagłówków
					Header +="\r\n" #wstawieni końca linii
					s.send(Header) #wysłanie nagłówka
					for d in datagen:
						if self._running: #sprawdzamy czy nie anulowano pobierania
							self.sent = self.sent + s.send(d) #wysłanie fragmentu danych i dodanie ich sumy do licznika danych
						else: #nastąpiło anulowanie
							s.close() #zamykamy połącznenie
							print "Abort..."
							return
					replay = s.recv(32) #odbieramy kilka danych z odpowidzie dla sprawdzenia statusu(tu może coś skopiuję z urllib2 ;))
					linia = replay.split("\r\n")
					if linia[0] == 'HTTP/1.1 200 OK': #tzn, że jest dobrze. Serwer przyją fotki :)
						self.status = 1 #zwiększamy licznik pozytywnych odpowiedzi  
					else:
						print replay
						self.status = 2#error
						self.info += replay
					s.close()
					
					
		def stop(self):
			self.photos=[]
			self._running = False 
			
		def running(self):
			return self._running
		
	class Galeria(threading.Thread):
		def __init__(self, hosts):
			self.Albums = {}
			self.ONLINE = False
			threading.Thread.__init__(self)
			self.hosts = hosts
			self.start()
			
		def run(self):
			self.ONLINE = True
			for host in self.hosts:
				if self.ONLINE:
					print u"Pobieranie albumów dla ", host
					self.getAlbums(host)
				else:
					return
		def stop(self):
			self.ONLINE=False
			
		def getAlbums(self,host,page=0): #standardowo co 10 albumów
			try:
				self.Albums[host]
			except KeyError:
				self.Albums[host]={}
				
			url = "http://"+host+"/galeria/pokaz/"+str(page)
			request = urllib2.Request(url)
			try:
				result = urllib2.urlopen(request)
			except urllib2.HTTPError, errno:
				return str(errno)
			html = result.read() #pobranie strony galerii
			p=BeautifulSoup(html) #wczytanie
			a = p.find(id='col_main_inv').findAll(attrs={'class' : 'elements'})
			 #odszukanie skrótów do galerii
			for i in a:
				album ={}
				id = i['id'].split('_')[-1]
				album['title'] = i.h3.a.string
				album['author'] = i.ul.li.a.string
				album['photos'] = i.div.div.find('strong').string
				album['thumbnail']="http://"+host+i.div.div.find('img')['src']
				if i.find(href='/galeria/dodaj/'+id):
					album['add']=1
				else:
					album['add']=0
				self.Albums[host][id] = album
				#print self.Albums[id]
	

	class _MyCookieJar(cookielib.CookieJar):
		'''Extend cookielib.CookieJar to generate Cookie with socjum_session as string'''
		def get_cookie(self):
			'''Return Cookie string for socjum.pl to add as header'''
			#print self._cookies #
			cookies=[]
			cookies_by_path = self._cookies['.socjum.pl']
			for path in cookies_by_path.keys():
				cookies_by_name = cookies_by_path[path]
				for cookie in cookies_by_name.values():
					cookies.append(cookie)
			Cookie = "Cookie: "+ "; ".join(self._cookie_attrs(cookies))
			return Cookie	
		

	
		